package com.tanhua.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

public class NioServer {

    public static void main(String[] args) throws IOException {

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(18080));
        serverSocketChannel.configureBlocking(false);

        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 注册完之后Selector就可以通过select方法来等等请求，
            // select方法有一个long类型的参数，代表最长等待时间，
            // 如果在这段时间里接收到了相应操作的请求则返回可以处理
            // 的请求的数量，否则在超时后返回0
//            // eg: 如果没接收到请求，10000毫秒后回返回0
//            int num = selector.select(10000L);
            int num = selector.select(); // 没有超时时间
//            System.out.println("selector获取到" + num + "个channel");
            if (num == 0) continue;
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                boolean connectable = selectionKey.isConnectable();
                boolean valid = selectionKey.isValid();
                boolean acceptable = selectionKey.isAcceptable();
                boolean readable = selectionKey.isReadable();
                boolean writable = selectionKey.isWritable();
//                System.out.println(connectable ? "connectable" : "");
//                System.out.println(valid ? "valid" : "");
//                System.out.println(acceptable ? "acceptable" : "");
//                System.out.println(readable ? "readable" : "");
//                System.out.println(writable ? "writable" : "");

                if (acceptable) {
                    System.out.println("连接成功!");
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    ByteBuffer byteBuffer = Charset.forName("UTF-8").encode("你已经成功连接服务器！");
                    socketChannel.write(byteBuffer);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }

                if (readable) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    socketChannel.configureBlocking(false);
                    try {
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        // 写入buffer
                        socketChannel.read(buffer);
                        // 从buffer读取并转换为char
                        buffer.flip();
                        System.out.println(Charset.defaultCharset().decode(buffer));
                    } catch (Exception e) {
                    }
                    socketChannel.register(selector, SelectionKey.OP_WRITE);
                }

                if (writable) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    socketChannel.configureBlocking(false);
                    try {
                        socketChannel.write(Charset.defaultCharset().encode("server已经收到你的信息。"));
                        System.out.println("server write");
                    } catch (Exception e) {
                    }
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }

            }
        }

    }
}